/**
 * 举报模型
 * @description 定义举报相关的数据结构和业务逻辑
 */

const mongoose = require('mongoose');

// 举报ID计数器模式
const reportIdCounterSchema = new mongoose.Schema({
    _id: { type: String, default: 'reportId' },
    sequence_value: { type: Number, default: 0 }
});

const ReportIdCounter = mongoose.model('ReportIdCounter', reportIdCounterSchema);

// 举报模式
const reportSchema = new mongoose.Schema({
    reportId: {
        type: Number,
        unique: true,
        required: true,
        description: '举报记录的唯一标识符，自动递增生成'
    },
    
    reporterId: {
        type: Number,
        required: true,
        index: true,
        description: '举报者的用户ID，关联到用户信息表'
    },
    
    targetType: {
        type: String,
        required: true,
        enum: ['video', 'comment', 'user', 'message'],
        index: true,
        description: '被举报对象的类型，可以是视频、评论、用户或私信'
    },
    
    targetId: {
        type: Number,
        required: true,
        index: true,
        description: '被举报对象的ID，根据targetType确定具体含义'
    },
    
    targetUserId: {
        type: Number,
        index: true,
        description: '被举报用户的ID，当举报对象涉及用户时使用'
    },
    
    reportType: {
        type: String,
        required: true,
        enum: [
            'spam',           // 垃圾信息
            'harassment',     // 骚扰
            'hate_speech',    // 仇恨言论
            'violence',       // 暴力内容
            'adult_content',  // 成人内容
            'copyright',      // 版权侵犯
            'misinformation', // 虚假信息
            'privacy',        // 隐私侵犯
            'fraud',          // 欺诈
            'other'           // 其他
        ],
        index: true,
        description: '举报类型，包括垃圾信息、骚扰、仇恨言论、暴力内容等'
    },
    
    reason: {
        type: String,
        required: true,
        maxlength: 500,
        description: '举报原因的简要说明，最大长度500字符'
    },
    
    description: {
        type: String,
        maxlength: 2000,
        description: '举报的详细描述，最大长度2000字符'
    },
    
    evidence: [{
        type: {
            type: String,
            enum: ['image', 'video', 'audio', 'document'],
            required: true,
            description: '证据文件类型'
        },
        url: {
            type: String,
            required: true,
            description: '证据文件的URL地址'
        },
        filename: {
            type: String,
            description: '证据文件的原始文件名'
        },
        size: {
            type: Number,
            description: '证据文件大小，单位为字节'
        }
    }],
    
    status: {
        type: String,
        enum: ['pending', 'reviewing', 'resolved', 'rejected', 'closed'],
        default: 'pending',
        index: true,
        description: '举报处理状态，包括待处理、审核中、已解决、已拒绝、已关闭'
    },
    
    priority: {
        type: String,
        enum: ['low', 'medium', 'high', 'urgent'],
        default: 'medium',
        index: true,
        description: '举报处理优先级，分为低、中、高、紧急四个级别'
    },
    
    handlerId: {
        type: Number,
        index: true,
        description: '处理该举报的管理员ID'
    },
    
    resolution: {
        action: {
            type: String,
            enum: ['no_action', 'warning', 'content_removal', 'account_suspension', 'account_ban', 'other'],
            description: '处理结果的具体行动'
        },
        reason: {
            type: String,
            description: '处理决定的原因'
        },
        details: {
            type: String,
            description: '处理结果的详细说明'
        },
        resolvedAt: {
            type: Date,
            description: '举报解决的时间'
        }
    },
    
    adminNotes: [{
        adminId: {
            type: Number,
            description: '添加备注的管理员ID'
        },
        note: {
            type: String,
            description: '管理员备注内容'
        },
        createAt: {
            type: Date,
            default: Date.now,
            description: '备注创建时间'
        }
    }],
    
    isDeleted: {
        type: Boolean,
        default: false,
        index: true,
        description: '软删除标记，true表示已删除，false表示正常状态'
    },
    
    reporterIp: {
        type: String,
        description: '举报者的IP地址，用于防止恶意举报和统计分析'
    },
    
    createAt: {
        type: Date,
        default: Date.now,
        index: true,
        description: '举报记录的创建时间'
    },
    
    updateAt: {
        type: Date,
        default: Date.now,
        description: '举报记录的最后更新时间'
    }
});

// 复合索引
reportSchema.index({ targetType: 1, targetId: 1 });
reportSchema.index({ reporterId: 1, createAt: -1 });
reportSchema.index({ status: 1, priority: -1, createAt: -1 });
reportSchema.index({ handlerId: 1, status: 1 });
reportSchema.index({ reportType: 1, status: 1 });

// 自动更新时间的中间件
reportSchema.pre('save', function(next) {
    this.updateAt = new Date();
    next();
});

// 自增reportId的中间件
reportSchema.pre('save', async function(next) {
    if (this.isNew) {
        try {
            const counter = await ReportIdCounter.findByIdAndUpdate(
                'reportId',
                { $inc: { sequence_value: 1 } },
                { new: true, upsert: true }
            );
            this.reportId = counter.sequence_value;
        } catch (error) {
            return next(error);
        }
    }
    next();
});

// 静态方法

/**
 * 创建举报
 * @param {Object} reportData - 举报数据
 * @returns {Object} 操作结果
 */
reportSchema.statics.createReport = async function(reportData) {
    try {
        // 检查是否重复举报
        const existingReport = await this.findOne({
            reporterId: reportData.reporterId,
            targetType: reportData.targetType,
            targetId: reportData.targetId,
            status: { $in: ['pending', 'reviewing'] },
            isDeleted: false
        });
        
        if (existingReport) {
            return {
                success: false,
                message: '您已经举报过该内容，请等待处理结果'
            };
        }
        
        const report = new this(reportData);
        await report.save();
        
        return {
            success: true,
            message: '举报提交成功',
            data: report.getSafeJSON()
        };
    } catch (error) {
        console.error('创建举报错误:', error);
        return {
            success: false,
            message: '举报提交失败'
        };
    }
};

/**
 * 获取举报列表
 * @param {Object} options - 查询选项
 * @returns {Object} 操作结果
 */
reportSchema.statics.getReportList = async function(options = {}) {
    try {
        const {
            status,
            reportType,
            targetType,
            priority,
            handlerId,
            reporterId,
            keyword,
            startDate,
            endDate,
            page = 1,
            limit = 20,
            sortBy = 'createAt',
            sortOrder = 'desc'
        } = options;
        
        // 构建查询条件
        const query = { isDeleted: false };
        
        if (status) query.status = status;
        if (reportType) query.reportType = reportType;
        if (targetType) query.targetType = targetType;
        if (priority) query.priority = priority;
        if (handlerId) query.handlerId = handlerId;
        if (reporterId) query.reporterId = reporterId;
        
        // 关键词搜索
        if (keyword) {
            query.$or = [
                { reason: { $regex: keyword, $options: 'i' } },
                { description: { $regex: keyword, $options: 'i' } }
            ];
        }
        
        // 时间范围
        if (startDate || endDate) {
            query.createAt = {};
            if (startDate) query.createAt.$gte = new Date(startDate);
            if (endDate) query.createAt.$lte = new Date(endDate);
        }
        
        // 排序
        const sort = {};
        sort[sortBy] = sortOrder === 'desc' ? -1 : 1;
        
        // 分页
        const skip = (page - 1) * limit;
        
        const [reports, total] = await Promise.all([
            this.find(query)
                .sort(sort)
                .skip(skip)
                .limit(limit)
                .lean(),
            this.countDocuments(query)
        ]);
        
        return {
            success: true,
            data: {
                reports: reports.map(report => ({
                    ...report,
                    evidence: report.evidence || [],
                    adminNotes: report.adminNotes || []
                })),
                pagination: {
                    page,
                    limit,
                    total,
                    pages: Math.ceil(total / limit)
                }
            }
        };
    } catch (error) {
        console.error('获取举报列表错误:', error);
        return {
            success: false,
            message: '获取举报列表失败'
        };
    }
};

/**
 * 获取举报详情
 * @param {Number} reportId - 举报ID
 * @returns {Object} 操作结果
 */
reportSchema.statics.getReportDetail = async function(reportId) {
    try {
        const report = await this.findOne({
            reportId,
            isDeleted: false
        }).lean();
        
        if (!report) {
            return {
                success: false,
                message: '举报不存在'
            };
        }
        
        return {
            success: true,
            data: {
                ...report,
                evidence: report.evidence || [],
                adminNotes: report.adminNotes || []
            }
        };
    } catch (error) {
        console.error('获取举报详情错误:', error);
        return {
            success: false,
            message: '获取举报详情失败'
        };
    }
};

/**
 * 更新举报状态
 * @param {Number} reportId - 举报ID
 * @param {String} status - 新状态
 * @param {Number} handlerId - 处理人员ID
 * @returns {Object} 操作结果
 */
reportSchema.statics.updateReportStatus = async function(reportId, status, handlerId) {
    try {
        const updateData = { status };
        if (handlerId) updateData.handlerId = handlerId;
        
        const report = await this.findOneAndUpdate(
            { reportId, isDeleted: false },
            updateData,
            { new: true }
        );
        
        if (!report) {
            return {
                success: false,
                message: '举报不存在'
            };
        }
        
        return {
            success: true,
            message: '状态更新成功',
            data: report.getSafeJSON()
        };
    } catch (error) {
        console.error('更新举报状态错误:', error);
        return {
            success: false,
            message: '状态更新失败'
        };
    }
};

/**
 * 处理举报
 * @param {Number} reportId - 举报ID
 * @param {Object} resolutionData - 处理结果数据
 * @param {Number} handlerId - 处理人员ID
 * @returns {Object} 操作结果
 */
reportSchema.statics.resolveReport = async function(reportId, resolutionData, handlerId) {
    try {
        const updateData = {
            status: 'resolved',
            handlerId,
            resolution: {
                ...resolutionData,
                resolvedAt: new Date()
            }
        };
        
        const report = await this.findOneAndUpdate(
            { reportId, isDeleted: false },
            updateData,
            { new: true }
        );
        
        if (!report) {
            return {
                success: false,
                message: '举报不存在'
            };
        }
        
        return {
            success: true,
            message: '举报处理完成',
            data: report.getSafeJSON()
        };
    } catch (error) {
        console.error('处理举报错误:', error);
        return {
            success: false,
            message: '举报处理失败'
        };
    }
};

/**
 * 添加管理员备注
 * @param {Number} reportId - 举报ID
 * @param {Number} adminId - 管理员ID
 * @param {String} note - 备注内容
 * @returns {Object} 操作结果
 */
reportSchema.statics.addAdminNote = async function(reportId, adminId, note) {
    try {
        const report = await this.findOneAndUpdate(
            { reportId, isDeleted: false },
            {
                $push: {
                    adminNotes: {
                        adminId,
                        note,
                        createAt: new Date()
                    }
                }
            },
            { new: true }
        );
        
        if (!report) {
            return {
                success: false,
                message: '举报不存在'
            };
        }
        
        return {
            success: true,
            message: '备注添加成功',
            data: report.getSafeJSON()
        };
    } catch (error) {
        console.error('添加管理员备注错误:', error);
        return {
            success: false,
            message: '备注添加失败'
        };
    }
};

/**
 * 删除举报
 * @param {Number} reportId - 举报ID
 * @returns {Object} 操作结果
 */
reportSchema.statics.deleteReport = async function(reportId) {
    try {
        const report = await this.findOneAndUpdate(
            { reportId, isDeleted: false },
            { isDeleted: true },
            { new: true }
        );
        
        if (!report) {
            return {
                success: false,
                message: '举报不存在'
            };
        }
        
        return {
            success: true,
            message: '举报删除成功'
        };
    } catch (error) {
        console.error('删除举报错误:', error);
        return {
            success: false,
            message: '举报删除失败'
        };
    }
};

/**
 * 获取举报统计信息
 * @param {Object} options - 统计选项
 * @returns {Object} 操作结果
 */
reportSchema.statics.getReportStats = async function(options = {}) {
    try {
        const { startDate, endDate, groupBy = 'status' } = options;
        
        // 构建匹配条件
        const matchCondition = { isDeleted: false };
        if (startDate || endDate) {
            matchCondition.createAt = {};
            if (startDate) matchCondition.createAt.$gte = new Date(startDate);
            if (endDate) matchCondition.createAt.$lte = new Date(endDate);
        }
        
        // 基础统计
        const [totalStats, statusStats, typeStats, priorityStats] = await Promise.all([
            // 总体统计
            this.aggregate([
                { $match: matchCondition },
                {
                    $group: {
                        _id: null,
                        total: { $sum: 1 },
                        pending: { $sum: { $cond: [{ $eq: ['$status', 'pending'] }, 1, 0] } },
                        reviewing: { $sum: { $cond: [{ $eq: ['$status', 'reviewing'] }, 1, 0] } },
                        resolved: { $sum: { $cond: [{ $eq: ['$status', 'resolved'] }, 1, 0] } },
                        rejected: { $sum: { $cond: [{ $eq: ['$status', 'rejected'] }, 1, 0] } }
                    }
                }
            ]),
            
            // 按状态统计
            this.aggregate([
                { $match: matchCondition },
                { $group: { _id: '$status', count: { $sum: 1 } } },
                { $sort: { count: -1 } }
            ]),
            
            // 按类型统计
            this.aggregate([
                { $match: matchCondition },
                { $group: { _id: '$reportType', count: { $sum: 1 } } },
                { $sort: { count: -1 } }
            ]),
            
            // 按优先级统计
            this.aggregate([
                { $match: matchCondition },
                { $group: { _id: '$priority', count: { $sum: 1 } } },
                { $sort: { count: -1 } }
            ])
        ]);
        
        return {
            success: true,
            data: {
                overview: totalStats[0] || {
                    total: 0,
                    pending: 0,
                    reviewing: 0,
                    resolved: 0,
                    rejected: 0
                },
                byStatus: statusStats,
                byType: typeStats,
                byPriority: priorityStats
            }
        };
    } catch (error) {
        console.error('获取举报统计错误:', error);
        return {
            success: false,
            message: '获取举报统计失败'
        };
    }
};

/**
 * 获取用户举报历史
 * @param {Number} reporterId - 举报者ID
 * @param {Object} options - 查询选项
 * @returns {Object} 操作结果
 */
reportSchema.statics.getUserReportHistory = async function(reporterId, options = {}) {
    try {
        const { page = 1, limit = 20, status } = options;
        
        const query = {
            reporterId,
            isDeleted: false
        };
        
        if (status) query.status = status;
        
        const skip = (page - 1) * limit;
        
        const [reports, total] = await Promise.all([
            this.find(query)
                .sort({ createAt: -1 })
                .skip(skip)
                .limit(limit)
                .select('reportId targetType targetId reportType reason status createAt')
                .lean(),
            this.countDocuments(query)
        ]);
        
        return {
            success: true,
            data: {
                reports,
                pagination: {
                    page,
                    limit,
                    total,
                    pages: Math.ceil(total / limit)
                }
            }
        };
    } catch (error) {
        console.error('获取用户举报历史错误:', error);
        return {
            success: false,
            message: '获取举报历史失败'
        };
    }
};

// 实例方法

/**
 * 获取安全的JSON数据（隐藏敏感信息）
 * @returns {Object} 安全的数据对象
 */
reportSchema.methods.getSafeJSON = function() {
    const obj = this.toObject();
    
    // 移除敏感信息
    delete obj._id;
    delete obj.__v;
    
    return obj;
};

/**
 * 检查是否可以编辑
 * @returns {Boolean} 是否可以编辑
 */
reportSchema.methods.canEdit = function() {
    return ['pending', 'reviewing'].includes(this.status);
};

/**
 * 检查是否可以删除
 * @returns {Boolean} 是否可以删除
 */
reportSchema.methods.canDelete = function() {
    return ['resolved', 'rejected', 'closed'].includes(this.status);
};

/**
 * 更新优先级
 * @param {String} priority - 新优先级
 * @returns {Promise} 更新结果
 */
reportSchema.methods.updatePriority = async function(priority) {
    this.priority = priority;
    return await this.save();
};

/**
 * 分配处理人员
 * @param {Number} handlerId - 处理人员ID
 * @returns {Promise} 更新结果
 */
reportSchema.methods.assignHandler = async function(handlerId) {
    this.handlerId = handlerId;
    this.status = 'reviewing';
    return await this.save();
};

const Reports = mongoose.model('Reports', reportSchema);

module.exports = Reports;